﻿using ReportingManagement.Components.Validation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ReportingManagement.Components.Queries
{
    /// <summary>
    /// Interaction logic for ReportParameterRetriever.xaml
    /// </summary>
    public partial class ReportParameterRetriever : UserControl
    {
        public static DependencyProperty ParameterNameProperty;
        public static DependencyProperty ParameterDescriptionProperty;
        public static DependencyProperty ValidatingRegularExpressionProperty;
        public static DependencyProperty ParameterValueProperty;
        public static DependencyProperty IsValidProperty;
        public static readonly RoutedEvent ParameterValueChangedEvent;

        static ReportParameterRetriever()
        {
            Type type = typeof(ReportParameterRetriever);
            FrameworkPropertyMetadata metadata = new FrameworkPropertyMetadata();
            metadata.DefaultValue = string.Empty;
            metadata.BindsTwoWayByDefault = true;
            metadata.PropertyChangedCallback = new PropertyChangedCallback(OnParameterNameChanged);
            ParameterNameProperty = DependencyProperty.Register("ParameterName", typeof(string), type, metadata);

            metadata = new FrameworkPropertyMetadata();
            metadata.DefaultValue = string.Empty;
            metadata.BindsTwoWayByDefault = true;
            metadata.PropertyChangedCallback = new PropertyChangedCallback(OnParameterDescriptionChanged);
            ParameterDescriptionProperty = DependencyProperty.Register("ParameterDescription", typeof(string), type, metadata);

            metadata = new FrameworkPropertyMetadata();
            metadata.DefaultValue = string.Empty;
            metadata.BindsTwoWayByDefault = true;
            metadata.PropertyChangedCallback = new PropertyChangedCallback(OnValidatingRegularExpressionChanged);
            ValidatingRegularExpressionProperty = DependencyProperty.Register("ValidatingRegularExpression", typeof(string), type, metadata);

            metadata = new FrameworkPropertyMetadata();
            metadata.DefaultValue = string.Empty;
            metadata.BindsTwoWayByDefault = true;
            metadata.PropertyChangedCallback = new PropertyChangedCallback(OnParameterValueChanged);
            ParameterValueProperty = DependencyProperty.Register("ParameterValue", typeof(string), type, metadata);

            metadata = new FrameworkPropertyMetadata();
            metadata.DefaultValue = false;
            metadata.BindsTwoWayByDefault = true;
            metadata.CoerceValueCallback = new CoerceValueCallback(CoerceIsValid);
            IsValidProperty = DependencyProperty.Register("IsValid", typeof(bool), type, metadata);

            ParameterValueChangedEvent = EventManager.RegisterRoutedEvent("ParameterValueChanged", RoutingStrategy.Bubble,
                typeof(RoutedPropertyChangedEventHandler<string>), type);
        }

        public string ParameterName
        {
            get { return (string)GetValue(ParameterNameProperty); }
            set { SetValue(ParameterNameProperty, value); }
        }

        public string ParameterDescription
        {
            get { return (string)GetValue(ParameterDescriptionProperty); }
            set { SetValue(ParameterDescriptionProperty, value); }
        }

        public string ValidatingRegularExpression
        {
            get { return (string)GetValue(ValidatingRegularExpressionProperty); }
            set { SetValue(ValidatingRegularExpressionProperty, value); }
        }

        public string ParameterValue
        {
            get { return (string)GetValue(ParameterValueProperty); }
            set { SetValue(ParameterValueProperty, value); }
        }

        public bool IsValid
        {
            get { return (bool)GetValue(IsValidProperty); }
            set { SetValue(IsValidProperty, value); }
        }

        public event RoutedPropertyChangedEventHandler<string> ParameterValueChanged
        {
            add { AddHandler(ParameterValueChangedEvent, value); }
            remove { RemoveHandler(ParameterValueChangedEvent, value); }
        }

        private static void OnParameterValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            string oldValue = (string)e.OldValue;
            string newValue = (string)e.NewValue;

            ReportParameterRetriever retriever = (ReportParameterRetriever)sender;
            RoutedPropertyChangedEventArgs<string> args = new RoutedPropertyChangedEventArgs<string>(oldValue, newValue);
            args.RoutedEvent = ReportParameterRetriever.ParameterValueChangedEvent;
            retriever.RaiseEvent(args);

            retriever.CoerceValue(IsValidProperty);
        }

        private static void OnValidatingRegularExpressionChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ReportParameterRetriever retriever = (ReportParameterRetriever)sender;
            retriever.txtParameterValue.Text = (string)e.OldValue;
        }

        private static void OnParameterDescriptionChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ReportParameterRetriever retriever = (ReportParameterRetriever)sender;
            retriever.txtDescription.Text = (string)e.NewValue;
        }

        private static void OnParameterNameChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ReportParameterRetriever retriever = (ReportParameterRetriever)sender;
            retriever.lblParameterName.Content = (string)e.NewValue;
        }

        private static object CoerceIsValid(DependencyObject sender, object baseValue)
        {
            ReportParameterRetriever retriever = (ReportParameterRetriever)sender;
            string value = retriever.ParameterValue;
            string expression = retriever.ValidatingRegularExpression;

            if (!string.IsNullOrWhiteSpace(expression) && !string.IsNullOrWhiteSpace(value))
            {
                bool valid = Regex.IsMatch(value, expression);
                return valid;
            }
            return false;
        }

        public ReportParameterRetriever()
        {
            InitializeComponent();
        }

        private void txtParameterValue_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox textBox = (TextBox)sender;
            string expression = this.ValidatingRegularExpression;            
            this.ParameterValue = textBox.Text;

            if (!string.IsNullOrWhiteSpace(expression) && !string.IsNullOrWhiteSpace(textBox.Text))
            {
                bool matched = Regex.IsMatch(textBox.Text, expression);
                if (matched) System.Windows.Controls.Validation.ClearInvalid(textBox.GetBindingExpression(TextBox.TextProperty));
                else
                {
                    RegexValidationRule regexValidation = new RegexValidationRule();
                    regexValidation.Expression = expression;

                    ValidationError error = new ValidationError(regexValidation, textBox.GetBindingExpression(TextBox.TextProperty));
                    error.ErrorContent = "The value does not agree with the validation rule";
                    System.Windows.Controls.Validation.MarkInvalid(textBox.GetBindingExpression(TextBox.TextProperty), error);
                }

                this.IsValid = matched;
            }
            else this.IsValid = false;
        }
    }
}
